/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.simba.apriori;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import java.util.HashMap;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import org.simba.utils.Configuration;

/**
 * Simply count the number of edges to a node to determine how "popular" it is
 * and uses the log of this count as a-priori score. Log is used because we assume
 * that we have a long-tail distribution of the number of edges for each node.
 * @author ngonga
 */
public class EdgeCount implements AprioriFunction {

    static Logger logger = Logger.getLogger("AEON");
    @Override
    
    /**
     * Computes to a-priori score based on a single uri
     * @param uri URI of the resource
     * @param endpoint SPARQL Endpoint for the query
     * @param graph Graph
     * @return A-priori score
     */    
     public double getAprioriScore(String uri, String endpoint, String graph) {
        String query = "SELECT ?x WHERE {?x ?p <"+uri+">}";
        Query sparqlQuery = QueryFactory.create(query);
        QueryExecution qexec;
        if (graph != null) {
            qexec = QueryExecutionFactory.sparqlService(endpoint, sparqlQuery, graph);
        } else {
            qexec = QueryExecutionFactory.sparqlService(endpoint, sparqlQuery);
        }
        ResultSet results = qexec.execSelect();
        int count = 0;
        try {
            while (results.hasNext()) {
                QuerySolution soln = results.nextSolution();
                count++;            
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
            logger.warn(e.getMessage());
        }
        //logger.info(uri+" -> "+Math.log(count+1));
        return Math.log(count+1);
    }

    /** Batch version
     * 
     * @param uris List of URIs
     * @param endpoint Endpoint for querying
     * @param graph Graph for the data
     * @return Map of uris to scores
     */
    @Override
    public HashMap<String, Double> getAprioriScore(TreeSet<String> uris, String endpoint, String graph) {
        HashMap<String, Double> result = new HashMap<String, Double>();
        for(String uri: uris)
        {
            result.put(uri, getAprioriScore(uri, endpoint, graph));
        }
        return result;
    }
    
    public static void main(String args[])
    {
        (new EdgeCount()).getAprioriScore("http://dbpedia.org/resource/Paris", 
                "http://live.dbpedia.org/sparql", null);
    }

    @Override
    public HashMap<String, Double> getAprioriScore(TreeSet<String> uris, Configuration c) {
        return getAprioriScore(uris, c.sparqlEndpoint, c.graph);
    }
    
}
